﻿#region Copyright

// All Material Copyright © 2010 Dynamic Concepts Development Corp., All Rights Reserved.
//      Portions Copyright © 1984-2009 Dynamic Concepts Development Corp., All Rights Reserved.
// For further information please contact: SoftwareSupport@dynconcepts.com
// Dynamic Concepts Development Corp.  311 W 57th St. Suite #422, New York, NY 10019

#endregion

#region Using References

using System;
using System.Threading;
using System.Windows.Threading;
using DynConDevCorp.OpenArch.SupportLibrary.ApplicationInfrastructure;
using DynConDevCorp.OpenArch.SupportLibrary.ParallelExecution;
using DynConDevCorp.OpenArch.SupportLibrary.ParallelExecution.Events;

#endregion

namespace DynConDevCorp.OpenArch.DynAppFramework.Tiers.UserInterface.WPF.Engine
{
    public static class CommandExecutionEnvironment
    {
        #region Public Methods

        public static void CreateExecutionThread()
        {
            s_ExecutionThread = new Thread(CreateApplicationThread);
            s_ExecutionThread.Name = "Command Execution Environment Thread";
            s_ExecutionThread.Start();
            WaitForThreadedInstanceStarted();
        }

        public static void Execute(Object originator, CommandEnvironmentDelegate action, object context, ParallelEventDispatchMode eventDispatchMode)
        {
            CommandExecutionEnvironmentEvent.DispatchMode = eventDispatchMode;
            CommandExecutionEnvironmentEvent.Execute(originator, new CommandExecutionEnvironmentEventArgs(action, context), EventCompleted);
        }

        #endregion

        #region Internal Methods

        internal static void ThreadedInstanceStarted()
        {
            sr_Sync.Release();
        }

        #endregion

        #region Private Methods

        private static void CommandExecutionEnvironmentThreadStarted(object sender, EventArgs args)
        {
            QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "CommandExecutionEnvironment.CommandExecutionEnvironmentThreadStarted()");
            ThreadedInstanceStarted();
        }

        private static void CreateApplicationThread()
        {
            ParallelHostThread.CreateNew(new CommandExecutionEnvironmentThreadedTask(), CommandExecutionEnvironmentThreadStarted);
        }

        private static void EventCompleted(object sender, EventArgs args)
        {
            QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "EventCompleted()");
        }

        private static void WaitForThreadedInstanceStarted()
        {
            sr_Sync.WaitOne();
        }

        #endregion

        #region Static Fields and Constants

        internal static readonly ParallelEvent<CommandExecutionEnvironmentEventArgs> CommandExecutionEnvironmentEvent = new ParallelEvent<CommandExecutionEnvironmentEventArgs>();
        private static Thread s_ExecutionThread;
        private static readonly Semaphore sr_Sync = new Semaphore(0, 1);

        #endregion
    }

    public delegate void CommandEnvironmentDelegate(object context);

    internal class CommandExecutionEnvironmentEventArgs : EventArgs
    {
        #region Constructors

        internal CommandExecutionEnvironmentEventArgs(CommandEnvironmentDelegate action, object context)
        {
            r_Action = action;
            r_Context = context;
        }

        #endregion

        #region Internal Properties and Indexers

        internal Delegate Action
        {
            get { return r_Action; }
        }

        internal object Context
        {
            get { return r_Context; }
        }

        #endregion

        #region Internal Methods

        internal void ExecuteAction()
        {
            if (r_Action != null)
            {
                r_Action(r_Context);
            }
        }

        #endregion

        #region Instance Fields (ReadOnly)

        private readonly CommandEnvironmentDelegate r_Action;
        private readonly object r_Context;

        #endregion
    }

    internal class CommandExecutionEnvironmentThreadedTask : DispatcherObject, IDisposable
    {
        #region Constructors

        internal CommandExecutionEnvironmentThreadedTask()
        {
            QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "CommandExecutionEnvironmentThreadedTask - Created !!!!!!!!");
            CommandExecutionEnvironment.CommandExecutionEnvironmentEvent.Add(new ParallelEventHandler<CommandExecutionEnvironmentEventArgs>(EventTarget), "Task");
        }

        #endregion

        #region Public Methods

        public void Dispose()
        {
            if (!m_Disposed)
            {
                m_Disposed = true;
                CommandExecutionEnvironment.CommandExecutionEnvironmentEvent.Remove(new ParallelEventHandler<CommandExecutionEnvironmentEventArgs>(EventTarget));
            }
        }

        #endregion

        #region Private Methods

        private void EventTarget(object sender, CommandExecutionEnvironmentEventArgs args)
        {
            QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "EventTarget() - Executed!!!!");
            if (args != null)
            {
                args.ExecuteAction();
            }
        }

        #endregion

        #region Instance Fields (Mutable)

        private bool m_Disposed;

        #endregion
    }
}